﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xaml;
using Bravura.Core.SynthLib.Model;
using Bravura.Editing.Common;
using Bravura.Editing.Common.Controls;
using Bravura.Editing.Common.Dialogs;
using Microsoft.Win32;
using Timer = System.Windows.Forms.Timer;
using Bravura.Editing.SynthEditor.Properties;

namespace Bravura.Editing.SynthEditor
{
	/// <summary>
	/// The main synth editor window.
	/// </summary>
	public partial class MainWindow : Window
	{
		#region Fields

		private Timer _statusTimer = new Timer();
		private FileInfo _fileInfo = null;
		private SynthProject _project = null;
		private bool _dirtyProj = false;
		private List<KeyValuePair<Type, Color>> _pluginColors = new List<KeyValuePair<Type, Color>>();

		#endregion

		public MainWindow()
		{
			this.InitializeComponent();
			_statusTimer.Tick += new EventHandler(StatusTimer_Tick);
			UpdateMenuStates();
			foreach (string entry in Settings.Default.PluginTypeColors)
			{
				string[] parts = entry.Split('=');
				Type type = Type.GetType(parts[0], true);
				Color color = (Color)ColorConverter.ConvertFromString(parts[1]);
				_pluginColors.Add(new KeyValuePair<Type,Color>(type, color));
			}
		}

		#region Event Handlers

		private void MenuItem_Click(object sender, RoutedEventArgs e)
		{
			HandleActionByName((sender as MenuItem).Tag as string);
		}

		private void StatusTimer_Tick(object sender, System.EventArgs e)
		{
			StatusLabel.Content = " ";
			_statusTimer.Enabled = false;
		}

		#endregion

		#region Private Methods

		private void HandleActionByName(string name)
		{
			switch (name)
			{
				#region File 

				case "FileNew":
				{
					if (_dirtyProj)
					{
						HandleDirtyProj();
					}
					if (!_dirtyProj)
					{
						NewProject();
					}
					break;
				}
				case "FileOpen":
				{
					if (_dirtyProj)
					{
						HandleDirtyProj();
					}
					if (!_dirtyProj)
					{
						OpenProject();
					}
					break;
				}
				case "FileSave":
				{
					if (_project != null)
					{
						if (_fileInfo != null)
						{
							SaveProject();
						}
						else
						{
							SaveProjectAs();
						}
					}
					else
					{
						DisplayErrorMessage("No project to save!");
					}
					break;
				}
				case "FileSaveAs":
				{
					if (_project != null)
					{
						SaveProjectAs();
					}
					else
					{
						DisplayErrorMessage("No project to save!");
					}
					break;
				}
				case "FileClose":
				{
					if (_dirtyProj)
					{
						HandleDirtyProj();
					}
					if (!_dirtyProj)
					{
						CloseProject();
					}
					break;
				}
				case "FilePrefs":
				{
					NullAction();
					break;
				}
				case "FileExit":
				{
					if (_dirtyProj)
					{
						HandleDirtyProj();
					}
					if (!_dirtyProj)
					{
						Application.Current.Shutdown();
					}
					break;
				}

				#endregion 

				#region Model

				case "ModelInfo":
				{
					NullAction();
					break;
				}
				case "ModelAdd":
				{
					NullAction();
					break;
				}
				case "ModelDel":
				{
					NullAction();
					break;
				}
				case "ModelRoute1M1M":
				{
					NullAction();
					break;
				}
				case "ModelRoute1S1S":
				{
					NullAction();
					break;
				}
				case "ModelRoute1S2M":
				{
					NullAction();
					break;
				}
				case "ModelRoute2M1S":
				{
					NullAction();
					break;
				}
				case "ModelManageConns":
				{
					NullAction();
					break;
				}
				case "ModelDisconn":
				{
					NullAction();
					break;
				}
				case "ModelTest":
				{
					NullAction();
					break;
				}

				#endregion

				#region Help

				case "HelpViewHelp":
				{
					Utilities.BrowseToWebPage(new Uri("http://bravura.codeplex.com/wikipage?title=Synth%20Editor"));
					break;
				}
				case "HelpAbout":
				{
					AboutWindow win = new AboutWindow();
					win.AppName = "Bravura Synth Editor";
					win.AppVersion = "0.0.0.0";
					win.AppLinkUri = "http://bravura.codeplex.com";
					win.AppLinkText = "bravura.codeplex.com";
					win.ShowDialog();
					break;
				}

				#endregion
			}

			UpdateMenuStates();
		}

		private void HandleDirtyProj()
		{
			if (_dirtyProj)
			{
				MessageBoxResult mbr = MessageBox.Show("You have unsaved changes. Would you like to save your changes first?", "Confirm", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
				if (mbr == MessageBoxResult.Yes)
				{
					SaveProject();
				}
				if (mbr == MessageBoxResult.No)
				{
					_dirtyProj = false;
				}
				if (mbr == MessageBoxResult.Cancel)
				{
					_dirtyProj = true;
				}
			}
		}

		private void NewProject()
		{
			_fileInfo = null;
			_project = new SynthProject { Name = "Untitled" };
			_dirtyProj = false;
			RefreshGrid();
		}

		private void OpenProject()
		{
			OpenFileDialog dlg = new OpenFileDialog();
			if (dlg.ShowDialog() == true)
			{
				object obj = XamlServices.Load(dlg.FileName);
				if (obj is SynthProject)
				{
					_fileInfo = new FileInfo(dlg.FileName);
					_project = obj as SynthProject;
					_dirtyProj = false;
				}
				else
				{
					DisplayErrorMessage("Not a valid SynthProject file.");
				}
			}
			RefreshGrid();
		}

		private void SaveProject()
		{
			if (_fileInfo != null)
			{
				XamlServices.Save(_fileInfo.FullName, _project);
				_dirtyProj = false;
			}
			else
			{
				SaveProjectAs();
			}
		}

		private void SaveProjectAs()
		{
			SaveFileDialog dlg = new SaveFileDialog();
			if (dlg.ShowDialog() == true)
			{
				_fileInfo = new FileInfo(dlg.FileName);
				SaveProject();
			}
		}

		private void CloseProject()
		{
			_fileInfo = null;
			_project = null;
			_dirtyProj = false;
		}

		private void UpdateMenuStates()
		{
			MenuFileNew.IsEnabled = true;
			MenuFileOpen.IsEnabled = true;
			MenuFileSave.IsEnabled = _project != null && _fileInfo != null;
			MenuFileSaveAs.IsEnabled = _project != null;
			MenuFileClose.IsEnabled = _project != null;
			MenuModel.IsEnabled = _project != null;
		}

		private void RefreshGrid()
		{
			WorkGrid.ClearChildren();
			foreach (PluginInfo info in _project.Plugins)
			{
				ItemIcon<PluginInfo> icon = CreatePluginIcon(info);
				WorkGrid.PlaceChild(info.MajorOrder, info.MinorOrder, icon);
			}
		}

		private ItemIcon<PluginInfo> CreatePluginIcon(PluginInfo info)
		{
			ItemIcon<PluginInfo> icon = new ItemIcon<PluginInfo>();

			Type t = Type.GetType(info.TypeName, true);

			icon.ItemColor = GetColorForType(t);
			icon.ItemType = GetNameForType(t);
			icon.ItemId = "#" + info.Num.ToString();
			icon.ItemName = info.Name;
			icon.WrappedItem = info;

			return icon;
		}

		private Color GetColorForType(Type t)
		{
			if (t != null)
			{
				foreach (var item in _pluginColors)
				{
					if (item.Key.IsAssignableFrom(t))
					{
						return item.Value;
					}
				}
			}

			return Color.FromArgb(255, 150, 150, 150);
		}

		private string GetNameForType(Type t)
		{
			if (t != null)
			{
				return t.Name;
			}

			return "Unknown";
		}

		private void NullAction()
		{
			DisplayStatusMessage("! Not Implemented !", 3000);
		}

		private void DisplayStatusMessage(string message, int timeout)
		{
			StatusLabel.Content = message;
			_statusTimer.Interval = timeout;
			_statusTimer.Enabled = true;
		}

		private void DisplayErrorMessage(string message)
		{
			MessageBox.Show(message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
		}

		#endregion
	}
}
